package com.evan.petiymanta.service;

import android.os.FileObserver;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;

import com.evan.petiymanta.model.BeanFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class FileService extends IFileExplorerService.Stub {
    private static final String TAG = "FileService";
    private final Map<String, FileObserver> observers = new HashMap<>();
    private final Handler handler = new Handler();

    @Override
    public List<BeanFile> listFiles(String path) throws RemoteException {
        List<BeanFile> files = new ArrayList<>();
        File[] fileList = new File(path).listFiles();
        if (fileList != null) {
            for (File file : fileList) {
                files.add(new BeanFile(
                        file.getName(),
                        file.getPath(),
                        file.isDirectory(),
                        false,
                        file.getName()
                ));
            }
        }
        return files;
    }

    @Override
    public boolean isFileExists(String path) throws RemoteException {
        return new File(path).exists();
    }

    @Override
    public String readFileContent(String path) throws RemoteException {
        try {
            File file = new File(path);
            byte[] content = new byte[(int) file.length()];
            try (FileInputStream fis = new FileInputStream(file)) {
                fis.read(content);
            }
            return new String(content, StandardCharsets.UTF_8);
        } catch (Exception e) {
            Log.e(TAG, "Error reading file: " + path, e);
            throw new RemoteException(e.getMessage());
        }
    }

    @Override
    public byte[] readImageFile(String path) throws RemoteException {
        try {
            File file = new File(path);
            byte[] bytes = new byte[(int) file.length()];
            try (FileInputStream fis = new FileInputStream(file)) {
                fis.read(bytes);
            }
            return bytes;
        } catch (Exception e) {
            Log.e(TAG, "Error reading image file: " + path, e);
            throw new RemoteException(e.getMessage());
        }
    }

    @Override
    public boolean deleteDirectory(String path) throws RemoteException {
        try {
            File dir = new File(path);
            if (dir.exists()) {
                deleteRecursively(dir);
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error deleting directory: " + path, e);
            throw new RemoteException(e.getMessage());
        }
    }

    private void deleteRecursively(File file) {
        if (file.isDirectory()) {
            for (File child : Objects.requireNonNull(file.listFiles())) {
                deleteRecursively(child);
            }
        }
        file.delete();
    }

    @Override
    public boolean copyDirectory(String sourcePath, String targetPath) throws RemoteException {
        try {
            File sourceDir = new File(sourcePath);
            File targetDir = new File(targetPath);
            copyRecursively(sourceDir, targetDir);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error copying directory: " + sourcePath + " to " + targetPath, e);
            throw new RemoteException(e.getMessage());
        }
    }

    private void copyRecursively(File source, File target) throws IOException {
        if (!source.exists()) {
            throw new IOException("Source does not exist: " + source);
        }

        if (source.isDirectory()) {
            if (!target.exists() && !target.mkdirs()) {
                throw new IOException("Failed to create directory: " + target);
            }

            String[] children = source.list();
            if (children != null) {
                for (String child : children) {
                    copyRecursively(
                            new File(source, child),
                            new File(target, child)
                    );
                }
            }
        } else {
            // 确保父目录存在
            File parentDir = target.getParentFile();
            if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
                throw new IOException("Failed to create parent directory: " + parentDir);
            }

            try (FileInputStream in = new FileInputStream(source);
                 FileOutputStream out = new FileOutputStream(target)) {
                byte[] buffer = new byte[8192];
                int read;
                while ((read = in.read(buffer)) != -1) {
                    out.write(buffer, 0, read);
                }
            }
        }
    }

    @Override
    public void startMonitoring(String projectPath, String backupPath) throws RemoteException {
        try {
            stopMonitoring(projectPath);

            Log.d(TAG, "Starting monitoring for: " + projectPath);

            // 先检查并删除 bin 目录
            File binDir = new File(projectPath, "bin");
            if (isFileExists(binDir.getAbsolutePath())) {
                Log.d(TAG, "Deleting existing bin directory");
                deleteDirectory(binDir.getAbsolutePath());
            }

            // 处理 SDK 文件
            File sdkDir = new File(projectPath, "apk/lib");
            if (isFileExists(sdkDir.getAbsolutePath())) {
                Log.d(TAG, "Backing up SDK files");
                // 确保备份目录存在
                File backupDir = new File(backupPath);
                if (!isFileExists(Objects.requireNonNull(backupDir.getParentFile()).getAbsolutePath())) {
                    new File(Objects.requireNonNull(backupDir.getParent())).mkdirs();
                }
                // 备份 SDK 文件
                copyDirectory(sdkDir.getAbsolutePath(), backupPath);
                // 删除原始 SDK 文件
                deleteDirectory(sdkDir.getAbsolutePath());
                Log.d(TAG, "SDK files backed up and removed");
            }

            // 启动定时检查
            Runnable checkTask = new Runnable() {
                @Override
                public void run() {
                    try {
                        File binDir = new File(projectPath, "bin");
                        if (binDir.exists() && binDir.isDirectory()) {
                            Log.d(TAG, "Bin directory detected, restoring SDK files");

                            // 创建 apk/lib 目录结构
                            File sdkDir = new File(projectPath, "apk/lib");
                            if (!isFileExists(sdkDir.getAbsolutePath())) {
                                // 从备份恢复
                                File backupDir = new File(backupPath);
                                if (isFileExists(backupPath)) {
                                    copyDirectory(backupPath, sdkDir.getAbsolutePath());
                                    deleteDirectory(backupPath);
                                    Log.d(TAG, "SDK files restored successfully");
                                }
                            }

                            // 停止监控
                            stopMonitoring(projectPath);
                        } else {
                            // 继续检查
                            handler.postDelayed(this, 3000);
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Error checking bin directory", e);
                    }
                }
            };

            // 开始定时检查
            handler.post(checkTask);
            observers.put(projectPath, null); // 标记为正在监控

            Log.d(TAG, "Monitoring started successfully");
        } catch (Exception e) {
            Log.e(TAG, "Error starting monitoring", e);
            throw new RemoteException(e.getMessage());
        }
    }

    @Override
    public void stopMonitoring(String projectPath) throws RemoteException {
        FileObserver observer = observers.remove(projectPath);
        if (observer != null) {
            observer.stopWatching();
            Log.d(TAG, "Monitoring stopped for: " + projectPath);
        }
    }
}